package com.example.demo.service.impl;

import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.aigc.generation.models.QwenParam;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;

import com.alibaba.dashscope.common.*;
import com.alibaba.dashscope.utils.Constants;
import com.example.demo.controller.AiController;
import com.example.demo.model.Chart;
import com.example.demo.model.Recommend;
import com.example.demo.utils.CommonMethod;
import org.json.JSONArray;
import org.json.JSONObject;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;


import java.io.BufferedReader;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


public class AiServiceImpl {
    /**
     * @Author XZH
     * @param message
     * @return
     * @throws NoApiKeyException
     * @throws ApiException
     * @throws InputRequiredException
     */
    // 直接就返回了结果
    public static String callWithMessage(String message) throws NoApiKeyException, ApiException, InputRequiredException {
        Generation gen = new Generation();
        // 免费的token 省着用
        Constants.apiKey = "sk-e1af2497e7464fc2a310ac7c2deab068";

        MessageManager msgManager = new MessageManager(2);
        Message systemMsg0 = Message.builder().role(Role.SYSTEM.getValue()).content("你是一个数据分析师和前端开发专家，接下来我会按照以下固定格式给你提供内容：\n分析需求：\n{数据分析的需求或者目标}\n原始数据：\n{csv格式的原始数据，用,作为分隔符}\n图表类型\n请根据这三部分内容，一定!要按照以下指定格式生成内容（此外一定不要输出任何多余的开头、结尾、注释！！）\n【【【【【{前端 Echarts V5 的 option 配置对象javascript代码，只是option的值，合理地将数据进行可视化，一定不要生成任何多余的内容，比如注释}\n】】】】】\n{明确的数据分析结论、越详细越好，不要生成多余的注释}\n不要出现function(value)\n").build();
        Message userMsg1 = Message.builder().role(Role.USER.getValue()).content(message).build();
        msgManager.add(systemMsg0);
        msgManager.add(userMsg1);

        QwenParam params = QwenParam.builder().model("qwen-turbo").messages(msgManager.get()).seed(1234).topP(0.8).resultFormat("message").enableSearch(false).maxTokens(1500).temperature((float) 0.85).repetitionPenalty((float) 1.0).build();

        GenerationResult result = gen.call(params);
        // 只取出了有效数据
        return result.getOutput().getChoices().get(0).getMessage().getContent();
    }

    public static String callWithMessageAndRole(String message, String role) throws NoApiKeyException, ApiException, InputRequiredException {
        Generation gen = new Generation();
        // 免费的token 省着用
        Constants.apiKey = "sk-e1af2497e7464fc2a310ac7c2deab068";

        MessageManager msgManager = new MessageManager(2);
        Message systemMsg0 = Message.builder().role(Role.SYSTEM.getValue()).content(role).build();
        Message userMsg1 = Message.builder().role(Role.USER.getValue()).content(message).build();
        msgManager.add(systemMsg0);
        msgManager.add(userMsg1);

        QwenParam params = QwenParam.builder().model("qwen-max").messages(msgManager.get()).seed(1234).topP(0.8).resultFormat("message").enableSearch(true).maxTokens(1500).temperature((float) 0.85).repetitionPenalty((float) 1.0).build();

        GenerationResult result = gen.call(params);
        // 只取出了有效数据
        return result.getOutput().getChoices().get(0).getMessage().getContent();
    }

    // 使用本地Ollama的qwen2模型进行询问
    public static String askLocalQwen2Model(String prompt) throws IOException {
        // 定义固定的URL
        String urlString = "http://localhost:11434/api/generate";
        URL url = new URL(urlString);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();

        // 设置请求方法为POST
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/json; utf-8");
        conn.setRequestProperty("Accept", "application/json");
        conn.setDoOutput(true);

        // 创建要发送的JSON对象
        JSONObject jsonInput = new JSONObject();
        jsonInput.put("model", "qwen2");
        jsonInput.put("prompt", prompt);
        jsonInput.put("stream", false);

        // 将JSON输入写入请求的输出流
        try (OutputStream os = conn.getOutputStream()) {
            byte[] input = jsonInput.toString().getBytes("utf-8");
            os.write(input, 0, input.length);
        }

        // 读取响应内容
        try (BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"))) {
            StringBuilder response = new StringBuilder();
            String responseLine;
            while ((responseLine = br.readLine()) != null) {
                response.append(responseLine.trim());
            }

            // 解析JSON响应并提取response字段
            JSONObject jsonResponse = new JSONObject(response.toString());
            return jsonResponse.getString("response");
        }
    }

    // 使用本地Ollama的微调后的echarts模型进行询问
    public static String askLocalEchartsModel(String prompt) throws IOException {
        // 定义固定的URL
        String urlString = "http://localhost:11434/api/generate";
        URL url = new URL(urlString);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();

        // 设置请求方法为POST
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/json; utf-8");
        conn.setRequestProperty("Accept", "application/json");
        conn.setDoOutput(true);

        // 创建要发送的JSON对象
        JSONObject jsonInput = new JSONObject();
        jsonInput.put("model", "Echarts");
        jsonInput.put("prompt", prompt);
        jsonInput.put("stream", false);

        // 将JSON输入写入请求的输出流
        try (OutputStream os = conn.getOutputStream()) {
            byte[] input = jsonInput.toString().getBytes("utf-8");
            os.write(input, 0, input.length);
        }

        // 读取响应内容
        try (BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"))) {
            StringBuilder response = new StringBuilder();
            String responseLine;
            while ((responseLine = br.readLine()) != null) {
                response.append(responseLine.trim());
            }

            // 解析JSON响应并提取response字段
            JSONObject jsonResponse = new JSONObject(response.toString());
            return jsonResponse.getString("response");
        }
    }

    // 使用本地AnythingLLM 加入echarts知识库后进行询问
    public static String askLocalAnythingLLM(String message) {
        final String TARGET_URL = "http://localhost:3001/api/v1/workspace/echarts/chat";
        final String ACCEPT_HEADER = "application/json";
        final String AUTHORIZATION_HEADER = "Bearer Y78TPJ6-5PJMMHB-Q07KE5B-07308GT";
        final String CONTENT_TYPE_HEADER = "application/json";
        StringBuilder response = new StringBuilder();
        try {
            // 创建URL对象
            URL url = new URL(TARGET_URL);

            // 打开连接
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();

            // 设置请求方法为POST
            connection.setRequestMethod("POST");

            // 设置请求头
            connection.setRequestProperty("accept", ACCEPT_HEADER);
            connection.setRequestProperty("Authorization", AUTHORIZATION_HEADER);
            connection.setRequestProperty("Content-Type", CONTENT_TYPE_HEADER);

            // 允许向连接中写入数据
            connection.setDoOutput(true);

            // 创建JSON请求体
            String jsonInputString = String.format("{ \"message\": \"%s\", \"mode\": \"query\" }", message);

            // 向连接中写入数据
            try (OutputStream os = connection.getOutputStream()) {
                byte[] input = jsonInputString.getBytes("utf-8");
                os.write(input, 0, input.length);
            }

            int responseCode = connection.getResponseCode();
            System.out.println("POST Response Code :: " + responseCode);

            // 读取响应内容
            try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"))) {
                String responseLine = null;
                while ((responseLine = br.readLine()) != null) {
                    response.append(responseLine.trim());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }


        // 创建JSONObject对象
        JSONObject jsonObject = new JSONObject(response.toString());
        // 提取textResponse字段
        String textResponse = jsonObject.getString("textResponse");

        return textResponse;
    }

    public static String genKeywordByUserActions(String message) throws NoApiKeyException, ApiException, InputRequiredException {
        Generation gen = new Generation();
        // 免费的token 省着用
        Constants.apiKey = "sk-e1af2497e7464fc2a310ac7c2deab068";

        MessageManager msgManager = new MessageManager(2);
        Message systemMsg0 = Message.builder().role(Role.SYSTEM.getValue()).content("你是一个分析大师，请你根据用户的以下行为，请给出一个关键词（只要求一个关键词，不要求分析即可），来精确描述用户的行为，这个关键词要展示出用户的爱好。").build();
        Message userMsg1 = Message.builder().role(Role.USER.getValue()).content(message).build();
        msgManager.add(systemMsg0);
        msgManager.add(userMsg1);

        QwenParam params = QwenParam.builder().model("qwen-turbo").messages(msgManager.get()).seed(1234).topP(0.8).resultFormat("message").enableSearch(false).maxTokens(1500).temperature((float) 0.85).repetitionPenalty((float) 1.0).build();

        GenerationResult result = gen.call(params);
        // 只取出了有效数据
        return result.getOutput().getChoices().get(0).getMessage().getContent();
    }

    /**
     * @Author YZQ
     * @param message
     * @return
     * @throws NoApiKeyException
     * @throws ApiException
     * @throws InputRequiredException
     */

    //为了实现地图的效果，调教一下AI
    public static String genMapData(String message) throws NoApiKeyException, ApiException, InputRequiredException {
        Generation gen = new Generation();
        // 免费的token 省着用
        Constants.apiKey = "sk-e1af2497e7464fc2a310ac7c2deab068";

        MessageManager msgManager = new MessageManager(2);
        Message systemMsg0 = Message.builder().role(Role.SYSTEM.getValue()).content("你是数据分析师，按以下固定格式给你内容：\n原始数据：\n{csv格式的原始数据，用,作为分隔符}" + "\n请你生成如下格式数据：(注意仅仅修改value！！！一定不要删除原始数据中不存在的省份！！！JSON格式！！！不要任何注释！！！)" + "      provinceData:[{name:'北京市',value:0},{name:'内蒙古自治区',value:0},{name:'黑龙江省',value:0},{name:'吉林省',value:0},{name:'辽宁省',value:0},\n" + "      {name:'甘肃省',value:0},{name:'宁夏回族自治区',value:0},{name:'陕西省',value:0},{name:'山西省',value:0},{name:'天津市',value:0},{name:'河北省',value:0},\n" + "      {name:'青海省',value:0},{name:'西藏自治区',value:0},{name:'新疆维吾尔自治区',value:0},{name:'四川省',value:0},{name:'重庆市',value:0},{name:'湖北省',value:0},\n" + "      {name:'河南省',value:0},{name:'山东省',value:0},{name:'江苏省',value:0},{name:'安徽省',value:0},{name:'上海市',value:0},{name:'浙江省',value:0},\n" + "      {name:'江西省',value:0},{name:'湖南省',value:0},{name:'福建省',value:0},{name:'台湾省',value:0},{name:'贵州省',value:0},{name:'云南省',value:0}\n" + "      ,{name:'广西壮族自治区',value:0},{name:'广东省',value:0},{name:'澳门特别行政区',value:0},{name:'香港特别行政区',value:0},{name:'海南省',value:0},{name:'南海诸岛',value:0}\n" + "      ]" + "\n①生成上述provinceData，②生成这样格式的【【结论】】，不需要任何其他信息！！").build();
        Message userMsg1 = Message.builder().role(Role.USER.getValue()).content(message).build();
        msgManager.add(systemMsg0);
        msgManager.add(userMsg1);

        QwenParam params = QwenParam.builder().model("qwen-turbo").messages(msgManager.get()).seed(1234).topP(0.8).resultFormat("message").enableSearch(false).maxTokens(1500).temperature((float) 0.85).repetitionPenalty((float) 1.0).build();

        GenerationResult result = gen.call(params);
        // 只取出了有效数据
        return result.getOutput().getChoices().get(0).getMessage().getContent();
    }

    //为了实现词云效果，调教一下AI
    public static String genWordCloudData(String message) throws NoApiKeyException, ApiException, InputRequiredException {
        Generation gen = new Generation();
        // 免费的token 省着用
        Constants.apiKey = "sk-e1af2497e7464fc2a310ac7c2deab068";

        MessageManager msgManager = new MessageManager(2);
        Message systemMsg0 = Message.builder().role(Role.SYSTEM.getValue()).content("你是数据分析师,给你一篇文本内容，请你提取关键的词语，并统计其出现的次数。并按照要求生成【摘要】。返回JSON格式例如如下：" + "WordCloud=[\n" + "    {\n" + "        \"name\": \"互联网服务\",\n" + "        \"value\": 10\n" + "    },\n" + "]" + "\n①生成上述WordCloud内容与文本有关，②生成的摘要格式：【【摘要】】，一定按照上述格式，不需要任何其他信息！！").build();
        Message userMsg1 = Message.builder().role(Role.USER.getValue()).content(message).build();
        msgManager.add(systemMsg0);
        msgManager.add(userMsg1);

        QwenParam params = QwenParam.builder().model("qwen-turbo").messages(msgManager.get()).seed(1234).topP(0.8).resultFormat("message").enableSearch(false).maxTokens(1500).temperature((float) 0.85).repetitionPenalty((float) 1.0).build();

        GenerationResult result = gen.call(params);
        // 只取出了有效数据
        return result.getOutput().getChoices().get(0).getMessage().getContent();
    }

    //为了实现关系图，调教一下AI
    public static String genGraphData(String message) throws NoApiKeyException, ApiException, InputRequiredException {
        Generation gen = new Generation();
        // 免费的token 省着用
        Constants.apiKey = "sk-e1af2497e7464fc2a310ac7c2deab068";

        MessageManager msgManager = new MessageManager(2);
        Message systemMsg0 = Message.builder().role(Role.SYSTEM.getValue()).content("你是数据分析师,给你一篇文本内容，将文本内容转换为关键的图的关系，并生成图的结构(不要任何注释)。并按照要求生成【摘要】。返回JSON格式内容不要过多与文本内容有关例如：" + "graph={\n" + "\"nodes\": [\n" + "{\"id\": \"0\", \"name\": \"软件工程\", \"symbolSize\": 10 ,\"x\": -266.82776,\n" + "\"y\": 299.6904,\n" + "\"value\": 5,\n" + "\"category\": 0},\n" + "{\"id\": \"1\", \"name\": \"计算机网络\", \"symbolSize\": 10, \"x\": -418.08344,\n" + "\"y\": 446.8853,\n" + "\"value\": 4,\n" + "\"category\": 0},\n" + "],\n" + "\"links\": [\n" + "{\"source\": \"0\", \"target\": \"1\"},\n" + "],\n" + "\"categories\": [\n" + "{\"name\": \"计算机科学\"},\n" + "]\n" + "}" + "\n①生成上述graph(注：x、y坐标随机生成即可；value为关键词出现次数要保留、value越大simbleSize越大，categories两三个即可)，②生成的摘要格式：【【摘要】】，不需要任何其他信息！！").build();
        Message userMsg1 = Message.builder().role(Role.USER.getValue()).content(message).build();
        msgManager.add(systemMsg0);
        msgManager.add(userMsg1);

        QwenParam params = QwenParam.builder().model("qwen-turbo").messages(msgManager.get()).seed(1234).topP(0.8).resultFormat("message").enableSearch(false).maxTokens(1500).temperature((float) 0.85).repetitionPenalty((float) 1.0).build();

        GenerationResult result = gen.call(params);
        // 只取出了有效数据
        return result.getOutput().getChoices().get(0).getMessage().getContent();
    }

    //为了实现思维导图，调教一下AI
    public static String genJsMind(String message) throws NoApiKeyException, ApiException, InputRequiredException {
        Generation gen = new Generation();
        // 免费的token 省着用
        Constants.apiKey = "sk-e1af2497e7464fc2a310ac7c2deab068";

        MessageManager msgManager = new MessageManager(2);

        Message systemMsg0 = Message.builder().role(Role.SYSTEM.getValue())
                .content("你是jsmind大师,给你一段文字，请你进行分析绘制简化的思维导图（出现关键信息即可），请你返回JSON格式数据，data中8条{}左右即可，,全部都是用parentid描述。一定要按照返回JSON格式例如："+
                       "\n" +
                        "{\n" +
                        "  \"meta\": {\n" +
                        "    \"name\": \"计量经济学入门与Python实现\",\n" +
                        "    \"author\": \"jsmind\"\n" +
                        "  },\n" +
                        "  \"format\": \"node_array\",\n" +
                        "  \"data\": [\n" +
                        "    {\n" +
                        "      \"id\": \"root\",\n" +
                        "      \"isroot\": true,\n" +
                        "      \"topic\": \"计量经济学与Python实践\"\n" +
                        "    },\n" +
                        "    {\n" +
                        "      \"id\": \"past\",\n" +
                        "      \"parentid\": \"root\",\n" +
                        "      \"topic\": \"之前使用Eviews的经验\"\n" +
                        "    },\n" +
                        "  ]\n" +
                        "}"
                        +"\n仅仅生成上述JSON格式数据，不需要任何其他信息如结论，注释！！"+
                        "\n要求1.节点关系仅仅能使用parentid;要求2.data数组中的对象属性不能出children等。必须按要求来！！！")
                .build();


        Message userMsg1 = Message.builder().role(Role.USER.getValue()).content(message).build();
        msgManager.add(systemMsg0);
        msgManager.add(userMsg1);

        QwenParam params = QwenParam.builder().model("qwen-turbo").messages(msgManager.get()).seed(1234).topP(0.8).resultFormat("message").enableSearch(false).maxTokens(1500).temperature((float) 0.85).repetitionPenalty((float) 1.0).build();

        GenerationResult result = gen.call(params);
        // 只取出了有效数据
        return result.getOutput().getChoices().get(0).getMessage().getContent();
    }

    //为了实现在线操作Excel，调教一下AI
    public static String genJsonData(String message) throws NoApiKeyException, ApiException, InputRequiredException {
        Generation gen = new Generation();
        // 免费的token 省着用
        Constants.apiKey = "sk-e1af2497e7464fc2a310ac7c2deab068";

        MessageManager msgManager = new MessageManager(2);

        Message systemMsg0 = Message.builder().role(Role.SYSTEM.getValue())
                .content("你是数据分析大师，下面给你一份由excel数据转换而来的JSON数据，其中第一个对象为表头，\n" +
                        "请你根据需求生成完整的JSON数据，在原始的基础上，增加或者减少。只要生成的JSON数据，不要任何其他信息，如注释。\n"+
                        "我知道你无法计算，所以如果需要计算，请你直接按如下格式进行，不要省略，要求完整的公式：\n"+
                        "{\"A\": \"平均值\", \"B\": “=(10+10+10)/3”}"
                        )
                .build();


        Message userMsg1 = Message.builder().role(Role.USER.getValue()).content(message).build();
        msgManager.add(systemMsg0);
        msgManager.add(userMsg1);

        QwenParam params = QwenParam.builder().model("qwen-turbo").messages(msgManager.get()).seed(1234).topP(0.8).resultFormat("message").enableSearch(false).maxTokens(1500).temperature((float) 0.85).repetitionPenalty((float) 1.0).build();

        GenerationResult result = gen.call(params);
        // 只取出了有效数据
        return result.getOutput().getChoices().get(0).getMessage().getContent();
    }

    public static void main(String[] args) {
        try {
            // 调用方法并打印返回结果
//            String response1 = askLocalQwen2Model("你好");
//            String response2 = askLocalEchartsModel("你好");
//            String response3 = askLocalLibraryModel("你好");
            String response4 = askLocalAnythingLLM("你好");
            System.out.println(response4);
//            System.out.println("Response: " + response1 + response2 + response3);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
